

#import "NSMPhotoBrowser.h"
#import "ALAssetsLibrary+CustomPhotoAlbum.h"

@interface CALayer (FadeAnimation)
- (void)addFadeAnimationWithDuration:(NSTimeInterval)duration curve:(UIViewAnimationCurve)curve;
- (void)removeFadeAnimation;
@end

@implementation CALayer (FadeAnimation)
- (void)addFadeAnimationWithDuration:(NSTimeInterval)duration curve:(UIViewAnimationCurve)curve {
    if (duration <= 0) return;
    
    NSString *mediaFunction;
    switch (curve) {
        case UIViewAnimationCurveEaseInOut:
            mediaFunction = kCAMediaTimingFunctionEaseInEaseOut;
            break;
        case UIViewAnimationCurveEaseIn:
            mediaFunction = kCAMediaTimingFunctionEaseIn;
            break;
        case UIViewAnimationCurveEaseOut:
            mediaFunction = kCAMediaTimingFunctionEaseOut;
            break;
        case UIViewAnimationCurveLinear:
            mediaFunction = kCAMediaTimingFunctionLinear;
            break;
        default:
            mediaFunction = kCAMediaTimingFunctionLinear;
            break;
    }
    
    CATransition *transition = [CATransition animation];
    transition.duration = duration;
    transition.timingFunction = [CAMediaTimingFunction functionWithName:mediaFunction];
    transition.type = kCATransitionFade;
    [self addAnimation:transition forKey:@"nsm.fade"];
}

- (void)removeFadeAnimation {
    [self removeAnimationForKey:@"nsm.fade"];
}
@end

#pragma mark - 扩展一个ProgressLayer
static const CGFloat kCircleWidth = 40.0f;
@interface NSMProgressLayer : CALayer
@property (nonatomic) CGFloat progress;
@property (nonatomic, strong) CAShapeLayer *progressLayer;
@end

@implementation NSMProgressLayer
- (instancetype)init {
    self = [super init];
    if (self) {
        [self initialize];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        [self initialize];
    }
    return self;
}

- (void)initialize {
    CGFloat kBorderWidth = 1.2f;
    CGFloat kPadding = 1.2f;
    CGFloat radius = kCircleWidth / 2;
    UIColor *kBorderColor = [UIColor whiteColor];
    UIColor *kBackgroundColor = WhiteColor(0, 0.5);
    UIColor *kProgressColor = [UIColor whiteColor];
    
    _progress = 0;
    
    self.frame = CGRectMake(0, 0, kCircleWidth, kCircleWidth);
    self.backgroundColor = kBackgroundColor.CGColor;
    self.cornerRadius = radius;
    self.borderWidth = kBorderWidth;
    self.borderColor = kBorderColor.CGColor;
    
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(radius, radius)
                                                        radius:(radius-kBorderWidth-kPadding) / 2
                                                    startAngle:-M_PI_2
                                                      endAngle:-M_PI_2 + 2*M_PI
                                                     clockwise:YES];
    _progressLayer = [CAShapeLayer layer];
    _progressLayer.frame = self.bounds;
    [self addSublayer:_progressLayer];
    
    _progressLayer.path = path.CGPath;
    _progressLayer.fillColor = [UIColor clearColor].CGColor;
    _progressLayer.strokeColor = kProgressColor.CGColor;
    _progressLayer.strokeStart = 0;
    _progressLayer.strokeEnd = 0;
    _progressLayer.lineCap = kCALineCapButt;
    _progressLayer.lineWidth = radius-kBorderWidth-kPadding;
    
}

- (void)setProgress:(CGFloat)progress {
    _progress = progress<0? 0: (progress>1? 1: progress);
    
    _progressLayer.strokeEnd = _progress;
}

@end

#pragma mark - 扩展一个NSMPhoto实体类
@interface NSMPhoto : NSObject
@property (nonatomic, strong) id imageSource;           // 大图
@property (nonatomic, strong) UIImage *thumbImage;      // 缩略图
@property (nonatomic, copy) NSString *title;            // 图片描述
@property (nonatomic, copy) NSString *subtitle;         // 图片详情
@property (nonatomic, assign) NSInteger index;
@property (nonatomic, assign) BOOL isFirstShow;
@end

@implementation NSMPhoto
#pragma mark - 缓存图片相关
+ (NSString *)pathForURL:(NSURL *)url inFolder:(NSString *)folderName {
    NSNumber *hashNumber = [NSNumber numberWithUnsignedInteger:url.description.hash];
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
    documentPath = [documentPath stringByAppendingPathComponent:folderName];
    BOOL isDirectory = YES;
    if (![fileManager fileExistsAtPath:documentPath isDirectory:&isDirectory]) {
        // 检查文件夹路径存在不存在,不存在则创建
        [[NSFileManager defaultManager] createDirectoryAtPath:documentPath
                                  withIntermediateDirectories:YES
                                                   attributes:nil
                                                        error:nil];
    }
    documentPath = [documentPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@",hashNumber]];
    
    return documentPath;
}

+ (BOOL)hasCacheImageAtURL:(NSURL *)url inFolder:(NSString *)folderName {
    return [[NSFileManager defaultManager] fileExistsAtPath:[NSMPhoto pathForURL:url inFolder:folderName]];
}

+ (UIImage *)cachedImageAtURL:(NSURL *)url inFolder:(NSString *)folderName {
    return [UIImage imageWithContentsOfFile:[NSMPhoto pathForURL:url inFolder:folderName]];
}

+ (void)cacheImage:(UIImage *)image url:(NSURL *)url inFolder:(NSString *)folderName {
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *documentPath = [NSMPhoto pathForURL:url inFolder:@"NSMPhotoBrowser"];
    [fileManager removeItemAtPath:documentPath error:nil];
    
    NSData *data = [image imageDataRepresentation];
    [fileManager createFileAtPath:documentPath contents:data attributes:nil];
}
@end

#pragma mark - 扩展一个NSMPhotoView图片类

#define kPadding 10.0f           // 两个图片间的间距
#define kMaxZoomScale 2.0f       // 最大缩放倍数
#define kToolbarHeight  44.0f    // 底部工具条默认高度
static NSString *const kNSMPhotoBrowserHide = @"kNotifacationSingleTapped";
static NSString *const kNSMPhotoBrowserSetSaveImage = @"kNSMPhotoBrowserSetImage";

@interface NSMPhotoView : UIScrollView <UIScrollViewDelegate>
@property (nonatomic, strong) NSMPhoto *photo;
@property (nonatomic, strong) UIView *containerView;
@property (nonatomic, strong) YYAnimatedImageView *imageView;
@property (nonatomic, strong) NSMProgressLayer *progressLayer;
@property (nonatomic) NSInteger currentIndex;
@property (nonatomic) CGRect originFrame;
- (void)reset;
@end

@implementation NSMPhotoView
- (instancetype)init {
    self = [super init];
    if (self) {
        // 基本属性
        self.frame = [UIScreen mainScreen].bounds;
        self.clipsToBounds = YES;
        self.delegate = self;
        self.backgroundColor = [UIColor clearColor];
        self.showsHorizontalScrollIndicator = NO;
        self.showsVerticalScrollIndicator = NO;
        self.decelerationRate = UIScrollViewDecelerationRateFast;
        self.autoresizingMask = UIViewAutoresizingFlexibleWidth |
        UIViewAutoresizingFlexibleHeight;
        
        // 展示的图片控件
        _containerView = [UIView new];
        _containerView.clipsToBounds = YES;
        [self addSubview:_containerView];
        
        _imageView = [YYAnimatedImageView new];
        _imageView.backgroundColor = WhiteColor(0, 0.5);
        [_containerView addSubview:_imageView];
        
        _progressLayer = [NSMProgressLayer layer];
        _progressLayer.hidden = YES;
        [self.layer addSublayer:_progressLayer];
        
        // 添加手势
        UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
        singleTap.numberOfTapsRequired = 1;
        [self addGestureRecognizer:singleTap];
        
        UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
        doubleTap.numberOfTapsRequired = 2;
        [self addGestureRecognizer:doubleTap];
        
        [singleTap requireGestureRecognizerToFail:doubleTap];
    }
    return self;
}

- (void)layoutSubviews {
    [super layoutSubviews];
    
    // 进度条居中
    _progressLayer.frame = CGRectMake((self.width - kCircleWidth) * 0.5, (self.height - kCircleWidth) * 0.5,
                                      kCircleWidth, kCircleWidth);
}

#pragma mark - 设置图片
- (void)setPhoto:(NSMPhoto *)photo {
    if (_photo == photo) return;
    _photo = photo;
    
    [self setZoomScale:1.0 animated:YES];
    self.maximumZoomScale = 1;
    
    [_imageView cancelCurrentImageRequest];
    [_imageView.layer removeFadeAnimation];
    
    _progressLayer.hidden = NO;
    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    _progressLayer.progress = 0;
    [CATransaction commit];
    
    if (!photo) {
        _imageView.image = nil;
        return;
    }
    
    [self loadImage];
    [self adjustFrame];
}

- (void)loadImage {
    if ([_photo.imageSource isKindOfClass:[UIImage class]]) {
        _progressLayer.hidden = YES;
        _imageView.image = _photo.imageSource;
    } else if ([_photo.imageSource isKindOfClass:[NSData class]]) {
        _progressLayer.hidden = YES;
        _imageView.image = [UIImage imageWithData:_photo.imageSource];
    } else {
        NSURL *url;
        if ([_photo.imageSource isKindOfClass:[NSURL class]])
            url = _photo.imageSource;
        else if ([_photo.imageSource isKindOfClass:[NSString class]])
            url = [NSURL URLWithString:_photo.imageSource];
        
        NSString *folderName = @"NSMPhotoBrowser";
        if ([NSMPhoto hasCacheImageAtURL:url inFolder:folderName]) {
            _progressLayer.hidden = YES;
            _imageView.image = [NSMPhoto cachedImageAtURL:url inFolder:folderName];
        } else {
            __weak typeof(self)weakSelf  = self;
            [_imageView setImageWithURL:url placeholder:_photo.thumbImage options:kNilOptions progress:^(NSInteger receivedSize, NSInteger expectedSize) {
                if (!weakSelf) return;
                CGFloat progress = receivedSize / (float)expectedSize;
                progress = progress < 0.01 ? 0.01 : progress > 1 ? 1 : progress;
                if (isnan(progress)) progress = 0;
                weakSelf.progressLayer.hidden = NO;
                weakSelf.progressLayer.progress = progress;
            } transform:nil completion:^(UIImage * image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) {
                if (!weakSelf) return;
                weakSelf.progressLayer.hidden = YES;
                if ((stage == YYWebImageStageFinished) && image) {
                    // [NSMPhoto cacheImage:image url:url inFolder:folderName];
                    [weakSelf adjustFrame];
                    [weakSelf.imageView.layer addFadeAnimationWithDuration:0.1 curve:UIViewAnimationCurveLinear];
                }
            }];
        }
    }
}

#pragma mark - 调整frame
- (void)adjustFrame {
    if (!_imageView.image) return;
    
    self.maximumZoomScale = kMaxZoomScale;
    _containerView.frame = CGRectMake(0, 0, self.width, 0);
    
    // 基本尺寸参数
    CGFloat screenScale = [UIScreen mainScreen].scale;
    CGSize boundsSize = self.bounds.size;
    CGSize imageSize = CGSizeMake(_imageView.image.size.width / screenScale,
                                  _imageView.image.size.height / screenScale);
    CGFloat imageScale = imageSize.height / imageSize.width;
    CGFloat superScale = boundsSize.height / boundsSize.width;
    
    // 将图片宽度设置和自身一样宽
    _containerView.height = (boundsSize.width / imageSize.width) * imageSize.height;
    if (imageScale < superScale)
        // 非长图时居中
        _containerView.centerY = boundsSize.height * 0.5;
    
    self.contentSize = CGSizeMake(boundsSize.width, MAX(_containerView.height, boundsSize.height));
    [self scrollRectToVisible:self.bounds animated:NO];
    
    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    _imageView.frame = _containerView.bounds;
    [CATransaction commit];
    
    [[NSNotificationCenter defaultCenter] postNotificationName:kNSMPhotoBrowserSetSaveImage object:_imageView.image];
}

#pragma mark - UIScrollViewDelegate
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
    return _containerView;
}

- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
    // 图像缩小时候始终居中(分别计算x-y的偏差)
    CGFloat offsetX = (scrollView.bounds.size.width > scrollView.contentSize.width)?
    (scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5 : 0.0;
    
    CGFloat offsetY = (scrollView.bounds.size.height > scrollView.contentSize.height)?
    (scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5 : 0.0;
    
    _containerView.center = CGPointMake(scrollView.contentSize.width * 0.5 + offsetX,
                                        scrollView.contentSize.height * 0.5 + offsetY);
}

#pragma mark - 手势
- (void)handleSingleTap:(UITapGestureRecognizer *)tap {
    [self setZoomScale:self.minimumZoomScale animated:NO];
    [UIView animateWithDuration:0.5 animations:^{
        self.alpha = 0;
    }completion:^(BOOL finished) {
        [[NSNotificationCenter defaultCenter] postNotificationName:kNSMPhotoBrowserHide object:self];
        self.userInteractionEnabled = YES;
    }];
}

- (void)handleDoubleTap:(UITapGestureRecognizer *)gesture {
    if (self.zoomScale == self.minimumZoomScale) {
        // 放大倍数(self.maximumZoomScale + self.minimumZoomScale)/2 ,这里取1.3
        CGFloat newScale = (self.maximumZoomScale + self.minimumZoomScale)/2;
        // 手势点击位置(放大中心点)
        CGPoint touchPoint = [gesture locationInView:gesture.view];
        CGRect zoomRect;
        // 显示的部分按比例缩小scale倍数，即为放大
        zoomRect.size.width = self.frame.size.width / newScale;
        zoomRect.size.height = self.frame.size.height / newScale;
        // 根据点击中心获得一个缩放矩形
        zoomRect.origin.x = touchPoint.x/self.zoomScale - zoomRect.size.width/2;
        zoomRect.origin.y = touchPoint.y/self.zoomScale - zoomRect.size.height/2;
        [self zoomToRect:zoomRect animated:YES];
    } else
        [self setZoomScale:self.minimumZoomScale animated:YES];
}

#pragma mark - 重置
- (void)reset {
    self.photo = nil;
    self.frame = [UIScreen mainScreen].bounds;
    _containerView.frame = self.bounds;
    _imageView.frame = _containerView.bounds;
    [_imageView cancelCurrentImageRequest];
}
@end

#pragma mark - 本体类的实现

@interface NSMPhotoBrowser () <UIScrollViewDelegate>
{
    UIScrollView    *_photoScrollView;  // 滑动视图
    NSMutableSet    *_visibleViews;     // 可见视图集合
    NSMutableSet    *_reusableViews;    // 回收的(可重用)视图集合
    
    NSMutableArray  *_photosArray;      // 图片对象集合
    NSInteger       _currentIndex;      // 当前展示的下标
    
    UIToolbar       *_toolbar;          // 工具条
    
    UIImage         *_saveImage;
    ALAssetsLibrary *_assetsLibrary;
}
@end

@implementation NSMPhotoBrowser

+ (instancetype)showPhotos:(NSArray *)photos thumbs:(NSArray *)thumbs atIndex:(NSInteger)index {
    return [[NSMPhotoBrowser alloc] initWithPhotos:photos
                                            thumbs:thumbs
                                           atIndex:index];
}

- (instancetype)initWithPhotos:(NSArray *)photos thumbs:(NSArray *)thumbs atIndex:(NSInteger)index {
    self = [super init];
    if (self) {
        // 初始化配置
        _currentIndex = index;
        _photosArray = [self arrayWithPhotos:photos thumbs:thumbs];
        
        _visibleViews = [NSMutableSet set];
        _reusableViews = [NSMutableSet set];
        
        _assetsLibrary = [[ALAssetsLibrary alloc] init];
        
        [self show];
    }
    return self;
}

- (NSMutableArray *)arrayWithPhotos:(NSArray *)photos thumbs:(NSArray *)thumbs {
    NSMutableArray *resultArray = [NSMutableArray array];
    
    NSInteger count = MAX(photos.count, thumbs.count);
    for (NSInteger i=0; i<count; i++) {
        NSMPhoto *photo = [[NSMPhoto alloc] init];
        photo.index = i;
        photo.isFirstShow = (i==_currentIndex? YES: NO);
        photo.thumbImage = (i<thumbs.count? thumbs[i]: nil);
        
        if (i < photos.count) {
            photo.title = photos[i][@"title"];
            photo.subtitle = photos[i][@"subtitle"];
            photo.imageSource = photos[i][@"photo"];
        }
        [resultArray addObject:photo];
    }
    
    return resultArray;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor blackColor];
    
    [self addScrollView];
    [self addToolbarControl];
}

- (void)hide {
    for (NSMPhotoView *photoView in _visibleViews) {
        [photoView reset];
    }
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    
    [self.view removeFromSuperview];
    [self removeFromParentViewController];
    
    [UIApplication sharedApplication].statusBarHidden = NO;
    [_keyWindow.rootViewController setNeedsStatusBarAppearanceUpdate];
}

- (void)show {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(changeSaveImage:) name:kNSMPhotoBrowserSetSaveImage object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(hide) name:kNSMPhotoBrowserHide object:nil];
    
    [_keyWindow.rootViewController addChildViewController:self];
    [_keyWindow addSubview:self.view];
    
    [UIApplication sharedApplication].statusBarHidden = YES;
    [_keyWindow.rootViewController setNeedsStatusBarAppearanceUpdate];
    
    [self showPhotos];
}

#pragma mark - 添加视图
- (void)addScrollView {
    CGRect frame = self.view.bounds;
    frame.origin.x -= kPadding;
    frame.size.width += kPadding * 2;
    
    _photoScrollView = [[UIScrollView alloc] initWithFrame:frame];
    _photoScrollView.delegate = self;
    _photoScrollView.pagingEnabled = YES;
    _photoScrollView.clipsToBounds = YES;
    _photoScrollView.delaysContentTouches = NO;
    _photoScrollView.backgroundColor = [UIColor clearColor];
    _photoScrollView.showsHorizontalScrollIndicator = NO;
    _photoScrollView.showsVerticalScrollIndicator = NO;
    _photoScrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth |
    UIViewAutoresizingFlexibleHeight;
    [self.view addSubview:_photoScrollView];
    
    _photoScrollView.contentSize = CGSizeMake(frame.size.width * _photosArray.count, 0);
    _photoScrollView.contentOffset = CGPointMake(_currentIndex * frame.size.width, 0);
}

- (void)addToolbarControl {
    CGRect toolbarFrame = CGRectMake(0,
                                     self.view.bounds.size.height - kToolbarHeight,
                                     self.view.bounds.size.width,
                                     kToolbarHeight);
    _toolbar = [[UIToolbar alloc] initWithFrame:toolbarFrame];
    _toolbar.barTintColor = nil;
    _toolbar.barStyle = UIBarStyleBlackTranslucent;
    _toolbar.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
    [_toolbar setBackgroundImage:nil forToolbarPosition:UIBarPositionAny barMetrics:UIBarMetricsDefault];
    [self.view addSubview:_toolbar];
    
    [self initToolbarItems];
    
    // 显示隐藏控制按钮
    UIButton *controlBtn = [UIButton buttonWithType:0];
    controlBtn.frame = CGRectMake(self.view.bounds.size.width-kToolbarHeight,
                                  self.view.bounds.size.height-44,
                                  44,
                                  kToolbarHeight);
    [controlBtn addTarget:self action:@selector(showOrHideToolbar:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:controlBtn];
    // icon 13*13
    controlBtn.imageEdgeInsets = UIEdgeInsetsMake((kToolbarHeight-13) / 2,
                                                  (44-13) / 2,
                                                  (kToolbarHeight-13) / 2,
                                                  (44-13) / 2);
    [controlBtn setImage:BundleImage(@"nsm_photo_browser_arrow") forState:UIControlStateNormal];
    controlBtn.imageView.transform = CGAffineTransformMakeRotation(M_PI);
    
    // 保存
    UIButton *saveBtn = [UIButton buttonWithType:0];
    saveBtn.frame = CGRectMake(CGRectGetMinX(controlBtn.frame)-44,
                               CGRectGetMinY(controlBtn.frame),
                               44,
                               kToolbarHeight);
    saveBtn.tintColor = COLOR_4;
    saveBtn.imageEdgeInsets = UIEdgeInsetsMake(14, 14, 14, 14);
    [saveBtn setImage:[BundleImage(@"nsm_photo_browser_save") imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal];
    [saveBtn addTarget:self action:@selector(savePhoto:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:saveBtn];
}

#pragma mark - toolbar相关
- (void)initToolbarItems {
    // 详情
    UILabel *subtitleLabel = [[UILabel alloc] init];
    subtitleLabel.tag = 100;
    subtitleLabel.numberOfLines = 0;
    subtitleLabel.textColor = [UIColor colorWithWhite:0.8 alpha:1];
    subtitleLabel.textAlignment = NSTextAlignmentLeft;
    subtitleLabel.font = [UIFont systemFontOfSize:14];
    [_toolbar addSubview:subtitleLabel];
    
    // 分割线
    UILabel *lineLabel = [[UILabel alloc] init];
    lineLabel.frame = CGRectMake(0,
                                 CGRectGetHeight(_toolbar.frame)-kToolbarHeight,
                                 CGRectGetWidth(_toolbar.frame),
                                 0.5);
    lineLabel.backgroundColor = [UIColor colorWithWhite:0.5 alpha:0.5];
    lineLabel.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
    [_toolbar addSubview:lineLabel];
    
    // 主标题
    UILabel *titleLabel = [[UILabel alloc] init];
    titleLabel.frame = CGRectMake(0,
                                  CGRectGetHeight(_toolbar.frame)-kToolbarHeight,
                                  CGRectGetWidth(_toolbar.frame)-44,
                                  kToolbarHeight);
    titleLabel.tag = 101;
    titleLabel.textColor = [UIColor colorWithWhite:0.8 alpha:1];
    titleLabel.textAlignment = NSTextAlignmentCenter;
    titleLabel.font = [UIFont systemFontOfSize:14];
    titleLabel.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
    [_toolbar addSubview:titleLabel];
}

- (void)showOrHideToolbar:(UIButton *)btn {
    BOOL isShowing = _toolbar.alpha;
    CGFloat height = CGRectGetHeight(_toolbar.frame);
    [UIView animateWithDuration:0.3 animations:^{
        btn.imageView.transform = isShowing? CGAffineTransformIdentity: CGAffineTransformMakeRotation(M_PI);
        
        self->_toolbar.alpha = isShowing? 0: 1;
        self->_toolbar.frame = CGRectMake(0,
                                    self.view.bounds.size.height-(isShowing? 0: height),
                                    self.view.bounds.size.width,
                                    height);
    }];
}

- (void)updateToolbarAtIndex:(NSInteger)index {
    if (!_toolbar) return;
    
    NSMPhoto *photo = _photosArray[index];
    NSNumber *currentIndex = [NSNumber numberWithInteger:index+1];
    NSNumber *totalCount = [NSNumber numberWithInteger:_photosArray.count];
    
    // 更新主标题
    UILabel *titleLabel = (UILabel *)[_toolbar viewWithTag:101];
    titleLabel.text = [NSString stringWithFormat:@"%@(%@ of %@)",photo.title,currentIndex,totalCount];
    
    // 更新副标题描述
    UILabel *subtitleLabel = (UILabel *)[_toolbar viewWithTag:100];
    subtitleLabel.text = photo.subtitle;
    
    CGFloat textHeight = 0;
    if (photo.subtitle.length && photo.subtitle) {
        CGSize size = [self sizeForString:photo.subtitle
                                     font:subtitleLabel.font
                                     size:CGSizeMake(CGRectGetWidth(_toolbar.frame)-20, MAXFLOAT)];
        textHeight = MAX(size.height+20, 40);
    }
    CGFloat newHeight = kToolbarHeight + textHeight;
    _toolbar.frame = CGRectMake(0,
                                self.view.bounds.size.height - newHeight,
                                self.view.bounds.size.width,
                                newHeight);
    subtitleLabel.frame = CGRectMake(10, 0, CGRectGetWidth(_toolbar.frame)-20, textHeight);
}

#pragma mark - calculate
- (CGSize)sizeForString:(NSString *)string font:(UIFont *)font size:(CGSize)size {
    CGRect newRect = [string boundingRectWithSize:size
                                          options:NSStringDrawingUsesLineFragmentOrigin
                                       attributes:@{NSFontAttributeName : font}
                                          context:nil];
    return newRect.size;
}

#pragma mark - 浏览图片
- (void)showPhotos {
    // bounds:{{0, 0}, {size.width+offset(左正右负), size.height}}
    CGRect visibleBounds = _photoScrollView.bounds;
    NSInteger firstIndex = (NSInteger)floorf((CGRectGetMinX(visibleBounds)+kPadding*2) / CGRectGetWidth(visibleBounds));
    NSInteger lastIndex  = (NSInteger)floorf((CGRectGetMaxX(visibleBounds)-kPadding*2) / CGRectGetWidth(visibleBounds));
    if (firstIndex < 0) firstIndex = 0;
    if (firstIndex >= _photosArray.count) firstIndex = _photosArray.count - 1;
    if (lastIndex < 0) lastIndex = 0;
    if (lastIndex >= _photosArray.count) lastIndex = _photosArray.count - 1;
    // 回收不再显示的ImageView
    for (NSMPhotoView *photoView in _visibleViews) {
        NSInteger index = photoView.photo.index;
        if (index < firstIndex || index > lastIndex) {
            // 回收之前把状态清空
            [photoView reset];
            [_reusableViews addObject:photoView];
            [photoView removeFromSuperview];
        }
    }
    // 移除相同的素
    [_visibleViews minusSet:_reusableViews];
    
    // 保持只重用队列只存在一个对象
    while (_reusableViews.count > 1)
        [_reusableViews removeObject:[_reusableViews anyObject]];
    
    for (NSUInteger index = firstIndex; index <= lastIndex; index++)
    {
        // 判断当前要展示的图片是否已经展示.
        if (![self isShowingPhotoViewAtIndex:index])
            [self showPhotoViewAtIndex:index];
    }
    
    // 取得拉到屏幕中间时候的index,更新对应的toolbar
    NSInteger controlIndex = floor((_photoScrollView.contentOffset.x + self.view.bounds.size.width/2) / _photoScrollView.bounds.size.width);
    if (controlIndex < 0)
        controlIndex = 0;
    if (controlIndex > _photosArray.count-1)
        controlIndex = _photosArray.count-1;
    [self updateToolbarAtIndex:controlIndex];
}

- (BOOL)isShowingPhotoViewAtIndex:(NSUInteger)index {
    for (NSMPhotoView *photoView in _visibleViews) {
        if (photoView.photo.index == index)
            return YES;
    }
    return  NO;
}

- (void)showPhotoViewAtIndex:(NSInteger)index {
    NSMPhotoView *photoView = [self dequeueReusablePhotoView];
    // 如果集合中不存在可重用的对象
    if (!photoView) {
        photoView = [NSMPhotoView new];
    }
    // 调整当期页的frame
    CGRect bounds = _photoScrollView.bounds;
    // 因为滚动视图可见范围左右多了kPadding差
    CGFloat originX = (bounds.size.width * index) + kPadding;;
    NSMPhoto *photo = _photosArray[index];
    photoView.left = originX;
    photoView.currentIndex = photo.index;
    [_visibleViews addObject:photoView];
    [_photoScrollView addSubview:photoView];
    
    photoView.photo = photo;
}

#pragma mark 循环利用某个view
- (NSMPhotoView *)dequeueReusablePhotoView {
    // 取集合中任意一对象重用
    NSMPhotoView *photoView = [_reusableViews anyObject];
    if (photoView)
        [_reusableViews removeObject:photoView];
    
    return photoView;
}

#pragma mark - 滚动视图代理
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    [self showPhotos];
}

#pragma mark - 保存图片
- (void)changeSaveImage:(NSNotification *)notification {
    if (![notification.object isKindOfClass:[UIImage class]]) return;
    _saveImage = notification.object;
}

- (void)savePhoto:(UIButton *)btn {
    _keyWindow.isLoading = YES;
    
    [_assetsLibrary saveImage:_saveImage toAlbum:kAppBundleName completion:^(NSURL *assetURL, NSError *error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            _keyWindow.isLoading = NO;
            [self showAlert:@"保存成功"];
        });
    } failure:^(NSError *error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            _keyWindow.isLoading = NO;
        });
    }];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

@end
